import time
import re
import sys
import json
import os.path
import urllib, urllib2
from datetime import datetime, timedelta
try:
    import whisper
except ImportError:
    raise SystemExit('[ERROR] Please make sure whisper is installed properly')
'''
statics
ip start end name interval stat_method value
'''
'''
config :
regex method
result :
ip start end name interval stat_method value
'''

STATIC_FUNCS = {}


class WspReader(object):
    def __init__(self, regstr, **kwargs):
        self.reg = re.compile(regstr)
        self.funcs = []
        if 'func_names' in kwargs:
            self.funcs = [
                STATIC_FUNCS[f] for f in kwargs['func_names']
                if f in STATIC_FUNCS
            ]
        now = int(time.time())
        self.start = now
        if 'from' in kwargs:
            self.start = self.start + kwargs['from']
        self.to = now
        if 'to' in kwargs:
            self.to = self.to + kwargs['to']

    def extract_from(self, file):
        m = self.reg.match(file)
        if m is not None:
            d = m.groupdict()
            if 'ip' in d and 'metric' in d:
                d['ip'] = d['ip'].replace('_', '.')
                d['metric'] = d['metric'].replace('/', '.')
                data = whisper.fetch(file, self.start, self.to)
                ret = {}
                for f in self.funcs:
                    ret = dict(ret, **f(data))
                return (d['ip'], d['metric'], ret)
            else:
                SystemExit('[ERROR] ip and metric shoud be in regex')
        return None


def post(baseurl, ip, metric, start, end, data):
    addr = os.path.join(baseurl, 'info/report', ip, metric)
    d = {}
    d['from'] = start
    d['to'] = end
    d['report'] = json.dumps(data)
    param = urllib.urlencode(d)
    f = urllib2.urlopen(addr, param)
    code = f.getcode()
    result = f.read()
    if code != 200:
        raise Exception('HTTP COEE:%d' % code)


#timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
def normal_gauge_value(data):
    (timeInfo, values) = data
    ret = {}
    ret['all_count'] = len(values)
    valid_values = sorted([value for value in values if value])
    ret['valid_count'] = len(valid_values)
    if ret['valid_count'] != 0:
        ret['min'] = valid_values[0]
        ret['max'] = valid_values[-1]
        ret['mid90'] = valid_values[int(len(valid_values) * 0.9) - 1]
        ret['mid50'] = valid_values[int(len(valid_values) * 0.5) - 1]
        ret['mid85'] = valid_values[int(len(valid_values) * 0.85) - 1]
        ret['avg'] = reduce(lambda x, y: x + y,
                            valid_values) / ret['valid_count']
    return ret


def normal_counter_value(data):
    (timeInfo, values) = data
    ret = {}
    ret['all_count'] = len(values)
    valid_values = sorted([value for value in values if value])
    ret['valid_count'] = len(valid_values)
    ret['delta'] = valid_values[-1] - valid_values[0]
    return ret


STATIC_FUNCS['mormal_gauge'] = normal_gauge_value
STATIC_FUNCS['mormal_counter'] = normal_counter_value
INTERVAL = 3600 * 24 * 7


def main():
    if len(sys.argv) < 4:
        raise SystemExit(
            '[ERROR] input args : \n 1.basedir  2.config_file  3.mondo url')
    base = sys.argv[1]
    url = sys.argv[3]
    readers = []
    with open(sys.argv[2]) as f:
        conf = json.load(f)
        readers = [WspReader(k, **v) for k, v in conf.items()]
    last_run_time = None
    while 1:
        if last_run_time is not None and last_run_time - int(time.time(
        )) < INTERVAL:
            print 'sleep'
            time.sleep(3600 * 6)
            continue
        print 'start'
        i = 0
        for root, dirs, files in os.walk(base):
            for f in files:
                if f.endswith('.wsp'):
                    fl = os.path.join(root, f)
                    for r in readers:
                        ret = r.extract_from(fl)
                        if ret is None:
                            continue
                        ip, metric, data = ret
                        start = r.start
                        to = r.to
                        try:
                            post(url, ip, metric, start, to, data)
                            i += 1
                        except Exception, ex:
                            print ex
        print 'end with %d result' % i
        last_run_time = int(time.time()) - 3600


if __name__ == "__main__":
    main()
